#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
编码类目表解析器模块
负责从编码类目表.txt文件中解析配置信息，转换为系统可使用的结构化配置
"""

import re
from pathlib import Path
from typing import Dict, List, Any, Optional


class CategoryConfigParser:
    """
    编码类目表解析器
    支持解析编码类目表.txt中的特殊语法，包括必填标记、选项和关键词
    """
    
    def __init__(self):
        """
        初始化解析器
        """
        # 类目表的结构化配置
        self._config: Dict[str, Any] = {}
        # 当前正在解析的类目
        self._current_category: Optional[str] = None
        # 当前正在解析的选项
        self._current_option: Optional[str] = None
        # 解析状态
        self._in_keywords_section = False
    
    def parse_file(self, file_path: str) -> Dict[str, Any]:
        """
        从文件路径解析编码类目表
        
        Args:
            file_path: 编码类目表.txt的文件路径
            
        Returns:
            解析后的结构化配置字典
            
        Raises:
            FileNotFoundError: 如果文件不存在
            ValueError: 如果文件格式错误
        """
        file = Path(file_path)
        if not file.exists():
            raise FileNotFoundError(f"编码类目表文件不存在: {file_path}")
        
        # 重置解析状态
        self._config = {}
        self._current_category = None
        self._current_option = None
        self._in_keywords_section = False
        
        with open(file_path, 'r', encoding='utf-8') as f:
            for line_number, line in enumerate(f, 1):
                line = line.strip()
                if not line or line.startswith('#'):
                    continue
                
                try:
                    self._parse_line(line)
                except Exception as e:
                    raise ValueError(f"解析第{line_number}行时出错: {line}\n错误信息: {str(e)}")
        
        return self._config
    
    def _parse_line(self, line: str) -> None:
        """
        解析单行内容
        
        Args:
            line: 当前解析的行
        """
        # 匹配类目定义行，如: () 场景设定/#这是一道单选题#/
        category_match = re.match(r'^\(\)\s+([^#]+)#([^#]*)#/', line)
        if category_match:
            self._handle_category_definition(category_match.group(1).strip(), 
                                           category_match.group(2).strip())
            return
        
        # 匹配必填标记
        if line == '<isrequired>':
            if self._current_category:
                self._config[self._current_category]['required'] = True
            return
        
        # 匹配选项行，如: 校园场景/#选项#/
        option_match = re.match(r'^([^#]+)#([^#]*)#/', line)
        if option_match:
            if self._current_category:
                option_name = option_match.group(1).strip()
                self._handle_option_definition(option_name)
            return
        
        # 匹配关键词行，如: <关键词=校园 OR 学校 OR 大学>
        keywords_match = re.match(r'^<关键词=(.*)>$', line)
        if keywords_match and self._current_category and self._current_option:
            keywords_str = keywords_match.group(1)
            self._handle_keywords(keywords_str)
    
    def _handle_category_definition(self, category_name: str, category_desc: str) -> None:
        """
        处理类目定义
        
        Args:
            category_name: 类目名称
            category_desc: 类目描述
        """
        self._current_category = category_name
        self._config[category_name] = {
            'description': category_desc,
            'required': False,
            'options': {}
        }
        self._current_option = None
    
    def _handle_option_definition(self, option_name: str) -> None:
        """
        处理选项定义
        
        Args:
            option_name: 选项名称
        """
        if self._current_category:
            self._current_option = option_name
            self._config[self._current_category]['options'][option_name] = {
                'keywords': []
            }
    
    def _handle_keywords(self, keywords_str: str) -> None:
        """
        处理关键词列表
        
        Args:
            keywords_str: 关键词字符串，格式如 "校园 OR 学校 OR 大学"
        """
        if self._current_category and self._current_option:
            # 分割OR关键词
            keywords = [kw.strip() for kw in keywords_str.split('OR')]
            self._config[self._current_category]['options'][self._current_option]['keywords'] = keywords
    
    def validate_config(self, config: Dict[str, Any]) -> tuple[bool, List[str]]:
        """
        验证解析后的配置是否有效
        
        Args:
            config: 解析后的配置字典
            
        Returns:
            (是否有效, 错误信息列表)
        """
        errors = []
        
        for category_name, category_data in config.items():
            # 检查必填字段
            if 'options' not in category_data or not category_data['options']:
                errors.append(f"类目 '{category_name}' 缺少选项")
                continue
            
            # 检查每个选项是否有关键词
            for option_name, option_data in category_data['options'].items():
                if 'keywords' not in option_data or not option_data['keywords']:
                    errors.append(f"类目 '{category_name}' 的选项 '{option_name}' 缺少关键词")
        
        return len(errors) == 0, errors


# 使用示例
if __name__ == '__main__':
    # 测试解析器
    parser = CategoryConfigParser()
    try:
        file_path = "../../data/编码类目表.txt"
        config = parser.parse_file(file_path)
        print("解析成功!")
        print(f"共解析到 {len(config)} 个类目")
        
        # 验证配置
        is_valid, errors = parser.validate_config(config)
        if is_valid:
            print("配置验证通过!")
        else:
            print("配置验证失败:")
            for error in errors:
                print(f"  - {error}")
        
        # 打印部分配置信息
        for category_name, category_data in config.items():
            print(f"\n类目: {category_name}")
            print(f"  必填: {category_data['required']}")
            print(f"  选项数: {len(category_data['options'])}")
            for option_name, option_data in category_data['options'].items():
                print(f"    选项: {option_name} (关键词数: {len(option_data['keywords'])})")
    
    except Exception as e:
        print(f"解析失败: {str(e)}")